package cn.itcast.n_formdataTest;

import org.activiti.engine.*;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.history.HistoricIdentityLink;
import org.activiti.engine.impl.persistence.entity.GroupEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.junit.Test;

import java.io.InputStream;
import java.util.*;

public class FormDataTest {

    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    /**
     * 部署流程定义（从inputStream）
     */
    @Test
    public void deploymentProcessDefinition_inputStream() {
        InputStream inputStreamBpmn = this.getClass().getResourceAsStream("formDataTest.bpmn");
        InputStream inputStreamPng = this.getClass().getResourceAsStream("formDataTest.png");
        Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
                .createDeployment()//创建一个部署对象
                .name("预算审批")//添加部署的名称
                .addInputStream("formDataTest.bpmn", inputStreamBpmn)//
                .addInputStream("formDataTest.png", inputStreamPng)//
                .deploy();//完成部署
        System.out.println("部署ID：" + deployment.getId());//
        System.out.println("部署名称：" + deployment.getName());//
    }

    /**
     * 启动流程实例
     */
    @Test
    public void startProcessInstance() {
        //流程定义的key
        String processDefinitionKey = "formDataTest";
        RuntimeService runTimeService = processEngine.getRuntimeService();
        TaskService taskService = processEngine.getTaskService();
        FormService formService = processEngine.getFormService();
        ProcessInstance pi = runTimeService//与正在执行的流程实例和执行对象相关的Service
                .startProcessInstanceByKey(processDefinitionKey, "business_456");//使用流程定义的key启动流程实例，key对应helloworld.bpmn文件中id的属性值，使用key值启动，默认是按照最新版本的流程定义启动
        System.out.println("流程实例ID:" + pi.getId());//流程实例ID
        System.out.println("流程定义ID:" + pi.getProcessDefinitionId());//流程定义ID


        //流程开始参数，设置填报期间
        Map<String, Object> p = new HashMap<String, Object>();
        p.put("period", "2013-07");
        //生成3家单位填报
        for (int i = 0; i < 3; i++) {
            //开始流程
            runTimeService.startProcessInstanceByKey("formDataTest", p);
            System.out.println("=====================kermit开始填报=======================");
            //querykermit'stasks;
            List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();
            for (Task task : tasks) {
                if ("fill".equals(task.getTaskDefinitionKey())) {
                    //设置填报人单位编码记录在节点
                    taskService.setVariableLocal(task.getId(), "accoutCode", "A110" + i);
                    //设置该流程实例的填报单位
                    taskService.setVariable(task.getId(), "fillAccount", "A110"
                            + i);
                    Map<String, FormProperty> propMap = createMap(formService.getTaskFormData(task.getId()).getFormProperties());
                    //获取节点报表打开类型
                    String fillType = (String) propMap.get("fillType").getValue();
                    //获取节点报表表单ID
                    String sheetId = (String) propMap.get("sheetId").getValue();
                    //获取节点是否需要汇总参数
                    String isSum = (String) propMap.get("isSum").getValue();
                    //获取节点填报单位编码
                    String accoutCode = (String) taskService.getVariableLocal(
                            task.getId(), "accoutCode");
                    //获取流程填报单位编码
                    String fillAccount = (String) taskService.getVariable(
                            task.getId(), "fillAccount");
                    //获取流程填报期间
                    String period = (String) taskService.getVariable(
                            task.getId(), "period");
                    //打印填报信息
                    System.out.println("\t打开报表类型：" + fillType);
                    System.out.println("\t填报表单：" + sheetId);
                    System.out.println("\t填报期间：" + period);
                    System.out.println("\t是否汇总：" + isSum);
                    System.out.println("\t当前节点账号：" + accoutCode);
                    System.out.println("\t提交审批表单填报单位：" + fillAccount);
                    //节点任务结束
                    taskService.complete(task.getId());
                    System.out
                            .println("=============kermit填写预算单任务已完成=====================");
                    System.out.println();
                }
            }
        }
    }

    /**
     * 查询当前人的个人任务
     */
    @Test
    public void findMyPersonalTask() {
        String assignee = "fozzie";
        List<Task> list = processEngine.getTaskService().createTaskQuery()//创建任务查询对象
                /**查询条件（where部分）*/
                .taskAssignee(assignee)//指定个人任务查询，指定办理人
//						.taskCandidateUser(candidateUser)//组任务的办理人查询
                /**排序*/
                .orderByTaskCreateTime().asc()//使用创建时间的升序排列
                /**返回结果集*/
                .list();//返回列表
        if (list != null && list.size() > 0) {
            for (Task task : list) {
                System.out.println("任务ID:" + task.getId());
                System.out.println("任务名称:" + task.getName());
                System.out.println("任务的创建时间:" + task.getCreateTime());
                System.out.println("任务的办理人:" + task.getAssignee());
                System.out.println("流程实例ID：" + task.getProcessInstanceId());
                System.out.println("执行对象ID:" + task.getExecutionId());
                System.out.println("流程定义ID:" + task.getProcessDefinitionId());
                System.out.println("########################################################");
            }
        }
    }

    /**
     * 单个审核
     */
    @Test
    public void singleCheck() {
        TaskService taskService = processEngine.getTaskService();
        FormService formService = processEngine.getFormService();
        System.out.println("=====================fozzie开始单个审核=======================");
        // query fozzie's tasks;
        List<Task> tasks2 = taskService.createTaskQuery()
                .taskAssignee("fozzie")
//                .processVariableValueEquals("period", "2013-07")
                .processDefinitionKey("formDataTest").list();
        int count = 1;
        for (Task task : tasks2) {
            if ("check".equals(task.getTaskDefinitionKey())) {
                System.out.println("\t审核第" + count + "个");
                // 设置节点审批人单位编码
                taskService.setVariableLocal(task.getId(), "accoutCode", "A1199");
                Map<String, FormProperty> propMap = createMap(formService.getTaskFormData(task.getId()).getFormProperties());
                // 获取节点报表打开类型
                String fillType = (String) propMap.get("fillType").getValue();
                // 获取节点报表表单ID
                String sheetId = (String) propMap.get("sheetId").getValue();
                // 获取节点是否需要汇总参数
                String isSum = (String) propMap.get("isSum").getValue();
                // 获取节点填报单位编码
                String accoutCode = (String) taskService.getVariableLocal(
                        task.getId(), "accoutCode");
                // 获取流程填报单位编码
                String fillAccount = (String) taskService.getVariable(
                        task.getId(), "fillAccount");
                // 获取流程填报期间
                String period = (String) taskService.getVariable(task.getId(),
                        "period");
                // 打印填报信息
                System.out.println("\t报表打开类型：" + fillType);
                System.out.println("\t填报表单：" + sheetId);
                System.out.println("\t填报期间：" + period);
                System.out.println("\t是否汇总：" + isSum);
                System.out.println("\t当前节点账号：" + accoutCode);
                System.out.println("\t提交审批表单填报单位：" + fillAccount);
                // 节点任务结束
                taskService.complete(task.getId());
                System.out.println("\t审核第" + count + "个完成");
                System.out.println();
                count++;
            }
        }
        System.out
                .println("===================fozzie审批预算单任务已完成===================");
        System.out.println();
    }


    /**
     * 汇总审核
     */
    @Test
    public void sum() {
        TaskService taskService = processEngine.getTaskService();
        FormService formService = processEngine.getFormService();
        System.out.println("=======================admin开始汇总审核=====================");
        List<Task> tasks3 = taskService.createTaskQuery()
                .taskAssignee("admin")
//                .processVariableValueEquals("period", "2013-07")
                .processDefinitionKey("formDataTest").list();
        // 批量审批列表
        List<String> completeTaskIdList = new ArrayList<String>();
        // 获取节点报表打开类型
        String fillType = "";
        // 获取节点报表表单ID
        String sheetId = "";
        // 获取节点是否需要汇总参数
        String isSum = "";
        // 获取流程填报期间
        String period = "";
        for (Task task : tasks3) {
            if ("sum".equals(task.getTaskDefinitionKey())) {
                // 设置节点审批人单位编码
                taskService.setVariableLocal(task.getId(), "accoutCode",
                        "A1199");
                // 获取流程填报单位编码
                String fillAccount = (String) taskService.getVariable(
                        task.getId(), "fillAccount");
                Map<String, FormProperty> propMap = createMap(formService
                        .getTaskFormData(task.getId()).getFormProperties());
                // 获取节点报表打开类型
                fillType = (String) propMap.get("fillType").getValue();
                // 获取节点报表表单ID
                sheetId = (String) propMap.get("sheetId").getValue();
                // 获取节点是否需要汇总参数
                isSum = (String) propMap.get("isSum").getValue();
                // 获取流程填报期间
                period = (String) taskService.getVariable(task.getId(),
                        "period");
                // 打印填报信息
                System.out.println("\t提交汇总审批表单填报单位：" + fillAccount);
                // 加入批量审批列表
                completeTaskIdList.add(task.getId());
            }
        }
        System.out.println("\t报表打开类型：" + fillType);
        System.out.println("\t填报表单：" + sheetId);
        System.out.println("\t填报期间：" + period);
        System.out.println("\t是否汇总：" + isSum);
        System.out.println("\t全部审批通过");
        for (String t : completeTaskIdList) {
            taskService.complete(t);
        }
        System.out.println("=========admin汇总预算单任务已完成，汇总审批" + completeTaskIdList.size() + "个单位=======");
    }


    /**
     * 查询正在执行的任务办理人表
     */
    @Test
    public void findRunPersonTask() {
        //任务ID
        String taskId = "6204";
        List<IdentityLink> list = processEngine.getTaskService()//
                .getIdentityLinksForTask(taskId);
        if (list != null && list.size() > 0) {
            for (IdentityLink identityLink : list) {
                System.out.println(identityLink.getTaskId() + "   " + identityLink.getType() + "   " + identityLink.getProcessInstanceId() + "   " + identityLink.getUserId());
            }
        }
    }

    /**
     * 查询历史任务的办理人表
     */
    @Test
    public void findHistoryPersonTask() {
        //流程实例ID
        String processInstanceId = "6201";
        List<HistoricIdentityLink> list = processEngine.getHistoryService()//
                .getHistoricIdentityLinksForProcessInstance(processInstanceId);
        if (list != null && list.size() > 0) {
            for (HistoricIdentityLink identityLink : list) {
                System.out.println(identityLink.getTaskId() + "   " + identityLink.getType() + "   " + identityLink.getProcessInstanceId() + "   " + identityLink.getUserId());
            }
        }
    }


    /**
     * 拾取任务，将组任务分给个人任务，指定任务的办理人字段
     */
    @Test
    public void claim() {
        //将组任务分配给个人任务
        //任务ID
        String taskId = "7504";
        //分配的个人任务（可以是组任务中的成员，也可以是非组任务的成员）
        String userId = "张三";
        processEngine.getTaskService()//
                .claim(taskId, userId);
    }


    /**
     * 将个人任务回退到组任务，前提，之前一定是个组任务
     */
    @Test
    public void setAssigee() {
        //任务ID
        String taskId = "6204";
        processEngine.getTaskService()//
                .setAssignee(taskId, null);
    }

    /**
     * 向组任务中添加成员
     */
    @Test
    public void addGroupUser() {
        //任务ID
        String taskId = "6204";
        //成员办理人
        String userId = "大H";
        processEngine.getTaskService()//
                .addCandidateUser(taskId, userId);
    }

    /**
     * 从组任务中删除成员
     */
    @Test
    public void deleteGroupUser() {
        //任务ID
        String taskId = "6204";
        //成员办理人
        String userId = "小B";
        processEngine.getTaskService()
                .deleteCandidateUser(taskId, userId);
    }


    private static Map<String, FormProperty> createMap(List<FormProperty> props) {
        Map<String, FormProperty> re = new HashMap<String, FormProperty>();
        for (FormProperty p : props) {
            re.put(p.getId(), p);
        }
        return re;
    }

}
